package com.yowasa.xiuxian.service.helper;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yowasa.xiuxian.constant.XiuxianConstants;
import com.yowasa.xiuxian.engine.CommonEngine;
import com.yowasa.xiuxian.engine.hone.SpecialInterface;
import com.yowasa.xiuxian.engine.item.ItemInterface;
import com.yowasa.xiuxian.entity.bo.item.UserItemBo;
import com.yowasa.xiuxian.entity.bo.user.UserAttr;
import com.yowasa.xiuxian.entity.bo.user.UserBO;
import com.yowasa.xiuxian.entity.bo.user.UserBattle;
import com.yowasa.xiuxian.entity.bo.user.UserConfig;
import com.yowasa.xiuxian.entity.bot.user.User;
import com.yowasa.xiuxian.entity.enums.ElementEnum;
import com.yowasa.xiuxian.entity.enums.StageEnum;
import com.yowasa.xiuxian.entity.mys.MysComponent;
import com.yowasa.xiuxian.entity.mys.SendMessage;
import com.yowasa.xiuxian.entity.po.XiuXianExtend;
import com.yowasa.xiuxian.entity.po.XiuxianUserBaseInfoPO;
import com.yowasa.xiuxian.entity.po.XiuxianUserEquip;
import com.yowasa.xiuxian.exception.HandlerException;
import com.yowasa.xiuxian.mapper.XiuxianExtendMapper;
import com.yowasa.xiuxian.mapper.XiuxianUserBaseInfoMapper;
import com.yowasa.xiuxian.mapper.XiuxianUserEquipMapper;
import com.yowasa.xiuxian.service.QQChannelService;
import com.yowasa.xiuxian.util.DateXUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;


@Component
public class UserHelper {
    public static final Logger logger = LoggerFactory.getLogger(UserHelper.class);
    private User bot;
    @Autowired
    private QQChannelService qqChannelService;
    @Autowired
    private MessageHelper messageHelper;
    @Autowired
    private XiuxianUserBaseInfoMapper xiuxianUserBaseInfoMapper;
    @Autowired
    private XiuxianUserEquipMapper xiuxianUserEquipMapper;
    @Autowired
    private UserTagHelper userTagHelper;
    @Autowired
    private XiuxianExtendMapper xiuxianExtendMapper;

    /**
     * 获取机器人本身信息
     *
     * @return
     */
    public User getBotInfo() {
        if (bot == null) {
            bot = qqChannelService.getBotInfo();
        }
        return bot;
    }

    /**
     * 依据id获取用户
     *
     * @param userId
     * @return
     */
    public UserBO getByUserId(String userId) {
        XiuxianUserBaseInfoPO po = xiuxianUserBaseInfoMapper.selectOne(new LambdaQueryWrapper<XiuxianUserBaseInfoPO>()
                .eq(XiuxianUserBaseInfoPO::getUserId, userId)
                .eq(XiuxianUserBaseInfoPO::getDead, 0)
        );
        if (po == null) {
            return null;
        }
        return UserBO.buildBO(po);
    }

    public UserBO getById(Long id) {
        XiuxianUserBaseInfoPO po = xiuxianUserBaseInfoMapper.selectById(id);
        if (po == null || po.getDead() == 1) {
            return null;
        }
        return UserBO.buildBO(po);
    }

    /**
     * 获取并校验当前用户
     *
     * @param message
     * @return
     */
    public UserBO checkOpUser(SendMessage message) {
        String userId = message.getFrom_user_id();
        XiuxianUserBaseInfoPO po = xiuxianUserBaseInfoMapper.selectOne(new LambdaQueryWrapper<XiuxianUserBaseInfoPO>()
                .eq(XiuxianUserBaseInfoPO::getUserId, userId)
                .eq(XiuxianUserBaseInfoPO::getDead, 0)
        );
        if (po == null) {
            List<MysComponent> list = new ArrayList<MysComponent>();
            MysComponent component = new MysComponent(",",2, "开始修仙","/开始修仙");
            list.add(component);
            List<List<MysComponent>> smallList = new ArrayList<>();
            smallList.add(list);
            messageHelper.replyMysPanel(message,"点击按钮创建你的玩家存档",smallList,null,null);
            throw new HandlerException("你还未创建用户，无法操作！请点击上方按钮执行指令 /开始修仙。");
        }
        UserBO user = UserBO.buildBO(po);
        if (user.getAge() > user.getUserConfig().getLife() && user.getLocal()!=99) {
            delUser(user);
//            messageHelper.replyMys(message, "你大限已至,求仙无门,老死家中");
            throw new HandlerException(user.getName() + "大限已至,求仙无门,老死家中");
        }
        return user;
    }

    public void checkCd(UserBO user) {
        if (user.getLockEndTime().compareTo(new Date()) > 0) {
            throw new HandlerException(user.getLockReason());
        }
    }

    public UserBO checkOpUserAll(SendMessage message) {
        UserBO user = checkOpUser(message);
        checkCd(user);
        checkUserState(user);
        return user;
    }

    public UserBO checkOpUserAndState(SendMessage message) {
        UserBO user = checkOpUser(message);
        checkUserState(user);
        return user;
    }

    private void checkUserState(UserBO user) {
        if (user.getUserBattle().getChp() <= 0) {
            throw new HandlerException("你的身体太差了,请先休养");
        }
    }


    /**
     * 获取并校验当前用户
     *
     * @param userBO
     * @return
     */
    public void saveUserInfo(UserBO userBO) {
        userBO.buildBaseInfo();
        xiuxianUserBaseInfoMapper.updateById(userBO);
    }

    public void rebuildBattleInfo(UserBO userBO) {
        UserBattle originBattle = userBO.getUserOriginBattle();
        Set<String> studiedSpecialEffect = userBO.getUserConfig().getStudiedSpecialEffect();
        UserBattle userBattle = new UserBattle();
        BeanUtils.copyProperties(originBattle, userBattle);
        for (String seStr : studiedSpecialEffect) {
            SpecialInterface special = CommonEngine.SPECIAL_EFFECT.get(seStr);
            if (special == null) {
                continue;
            }
            special.effectBattle(userBO,userBattle);
        }
        userBO.setUserBattle(userBattle);
        List<XiuxianUserEquip> xiuxianUserEquips = xiuxianUserEquipMapper.selectList(new LambdaQueryWrapper<XiuxianUserEquip>()
                .eq(XiuxianUserEquip::getAccountId,userBO.getId()));
        for (XiuxianUserEquip equip : xiuxianUserEquips){
            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(equip.getItemName());
            UserItemBo itemBo = new UserItemBo();
            itemBo.setItemAttr(equip.getItemAttr());
            itemInterface.effectEquip(userBO,itemBo);
        }

        int value = userTagHelper.getValue(userBO.getUserId(), XiuxianConstants.BAIDUAN_TIMES);
        double v = 0.05 * value;
        userBO.getUserBattle().setHp((int) (userBO.getUserBattle().getHp() + userBO.getUserOriginBattle().getHp() * v));
        userBO.getUserBattle().setMp((int) (userBO.getUserBattle().getMp() + userBO.getUserOriginBattle().getMp() * v));
        userBO.getUserBattle().setAtk((int) (userBO.getUserBattle().getAtk() + userBO.getUserOriginBattle().getAtk() * v));
        userBO.getUserBattle().setSpell((int) (userBO.getUserBattle().getSpell() + userBO.getUserOriginBattle().getSpell() * v));
        userBO.getUserBattle().setDef((int) (userBO.getUserBattle().getDef() + userBO.getUserOriginBattle().getDef() * v));
        userBO.getUserBattle().setRes((int) (userBO.getUserBattle().getRes() + userBO.getUserOriginBattle().getRes() * v));
        userBO.getUserBattle().setSpd((int) (userBO.getUserBattle().getSpd() + userBO.getUserOriginBattle().getSpd() * v));
        userBO.getUserBattle().setImm((int) (userBO.getUserBattle().getImm() + userBO.getUserOriginBattle().getImm() * v));
        //保存
        xiuxianUserBaseInfoMapper.updateById(userBO);
    }


    public void delUser(UserBO user) {
//        localHelper.delUser2Local(user, MapEnum.getById(user.getLocal()));
        xiuxianUserBaseInfoMapper.update(null, new LambdaUpdateWrapper<XiuxianUserBaseInfoPO>()
                .set(XiuxianUserBaseInfoPO::getDead, 1)
                .set(XiuxianUserBaseInfoPO::getDeadAt, new Date())
                .eq(XiuxianUserBaseInfoPO::getUserId, user.getUserId())
        );
        userTagHelper.setValue(user.getUserId(), XiuxianConstants.BAIDUAN_TIMES,0);
    }

    public int addExp(UserBO user, int exp) {
        Integer code = user.getStage();
        Integer level = user.getLevel();
        StageEnum stage = StageEnum.getById(code);
        int need = stage.getNeed();
        int totalExp = user.getUserConfig().getLeftExp() + exp;
        level += totalExp / need;
        int outLevel = 0;
        int left = totalExp % need;
        if (level > 100) {
            outLevel = level - 100;
            level = 100;
            left = 0;
        }
        user.setLevel(level);
        user.getUserConfig().setLeftExp(left);
        return outLevel;
    }

    /**
     * 锁定用户
     *
     * @param userBO
     * @param days
     * @param reason
     */
    public void lockUser(UserBO userBO, int days, String reason) {
        Date to = DateXUtil.getTo(days);
        userBO.setLockEndTime(to);
        userBO.setLockReason(reason + "[" + DateXUtil.formatTime(to) + "]");
    }

    public UserBO initUser(String name) {
        UserBO bo = new UserBO();
        bo.setName(name);
        bo.setStage(1);
        bo.setLevel(0);
        bo.setUserAttr(UserAttr.genAttr());
        UserBattle userBattle = UserBattle.genBattleAttr(bo.getUserAttr());
        bo.setUserBattle(userBattle);
        bo.setUserOriginBattle(userBattle);
        bo.setElement(ElementEnum.genLingGen());
        bo.setUserConfig(new UserConfig());
        bo.setStartAt(new Date());
        bo.setAge(DateXUtil.START_AGE);
        bo.buildBaseInfo();
        return bo;
    }

    //处理修仙历史加成
    public void calHistoryUpper(UserBO userBO) {
        calFeiShengAttrUpper(userBO);
    }

    //飞升属性提升
    public void calFeiShengAttrUpper(UserBO userBO) {
        //飞升加成
        int value = userTagHelper.getValue(userBO.getUserId(), XiuxianConstants.TAG_FEISHENG);
        if (value > 0) {
            UserAttr userAttr = userBO.getUserAttr();
            userAttr.upFull(value);
        }
    }

    public List<UserBO> getBattleFieldList(UserBO firstUser, XiuXianExtend byAccountId) {
        Integer fieldNum = byAccountId.getBattleField();
        if(fieldNum == 0) {
            int i = firstUser.getStage() - 2;
            fieldNum = i;
            byAccountId.setBattleField(i);
            xiuxianExtendMapper.updateById(byAccountId);
        }
        List<XiuxianUserBaseInfoPO> xiuxianUserBaseInfoPOS = xiuxianUserBaseInfoMapper.selectList(
                new LambdaQueryWrapper<XiuxianUserBaseInfoPO>()
                        .eq(XiuxianUserBaseInfoPO::getGuildId, "battleField" + fieldNum));
        List<UserBO> userBOList = new ArrayList<UserBO>();
        xiuxianUserBaseInfoPOS.forEach(e -> {
            userBOList.add(UserBO.buildBO(e));
        });
        return userBOList;
    }


    public void rebuildBattleInfoEquip(UserBO userBO) {
        int nowHp = userBO.getUserBattle().getChp();
        int nowMp = userBO.getUserBattle().getCmp();
        UserBattle originBattle = userBO.getUserOriginBattle();
        Set<String> studiedSpecialEffect = userBO.getUserConfig().getStudiedSpecialEffect();
        UserBattle userBattle = new UserBattle();
        BeanUtils.copyProperties(originBattle, userBattle);
        for (String seStr : studiedSpecialEffect) {
            SpecialInterface special = CommonEngine.SPECIAL_EFFECT.get(seStr);
            if (special == null) {
                continue;
            }
            special.effectBattle(userBO,userBattle);
        }
        userBO.setUserBattle(userBattle);
        List<XiuxianUserEquip> xiuxianUserEquips = xiuxianUserEquipMapper.selectList(new LambdaQueryWrapper<XiuxianUserEquip>()
                .eq(XiuxianUserEquip::getAccountId,userBO.getId()));
        for (XiuxianUserEquip equip : xiuxianUserEquips){
            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(equip.getItemName());
            UserItemBo itemBo = new UserItemBo();
            itemBo.setItemAttr(equip.getItemAttr());
            itemInterface.effectEquip(userBO,itemBo);
        }

        int value = userTagHelper.getValue(userBO.getUserId(), XiuxianConstants.BAIDUAN_TIMES);
        double v = 0.05 * value;
        userBO.getUserBattle().setHp((int) (userBO.getUserBattle().getHp() + userBO.getUserOriginBattle().getHp() * v));
        userBO.getUserBattle().setMp((int) (userBO.getUserBattle().getMp() + userBO.getUserOriginBattle().getMp() * v));
        userBO.getUserBattle().setAtk((int) (userBO.getUserBattle().getAtk() + userBO.getUserOriginBattle().getAtk() * v));
        userBO.getUserBattle().setSpell((int) (userBO.getUserBattle().getSpell() + userBO.getUserOriginBattle().getSpell() * v));
        userBO.getUserBattle().setDef((int) (userBO.getUserBattle().getDef() + userBO.getUserOriginBattle().getDef() * v));
        userBO.getUserBattle().setRes((int) (userBO.getUserBattle().getRes() + userBO.getUserOriginBattle().getRes() * v));
        userBO.getUserBattle().setSpd((int) (userBO.getUserBattle().getSpd() + userBO.getUserOriginBattle().getSpd() * v));
        userBO.getUserBattle().setImm((int) (userBO.getUserBattle().getImm() + userBO.getUserOriginBattle().getImm() * v));

        userBO.getUserBattle().setCmp(nowMp);
        userBO.getUserBattle().setChp(nowHp);
        //保存
        xiuxianUserBaseInfoMapper.updateById(userBO);
    }

    public void insertDataBind(String userId, String s) {
        xiuxianExtendMapper.insertDataBind(userId,s);
    }

    public String selectBindKey(String userId) {
        return xiuxianExtendMapper.selectBindKey(userId);
    }
}
